package com.jin.webvideo.websocket.shareroom.entity;

import com.jin.webvideo.util.sys.EncryptUtil;

import java.io.IOException;
import java.nio.ByteBuffer;

public class MsgIO {
    public static ByteBuffer write(BinMessage message) throws IOException, BadMessageException {
        int len = message.getPayload().length;
        ByteBuffer byteBuffer = ByteBuffer.allocate(5 + BinMessage.MASKKEY_LEN + BinMessage.CHECKSUM_LEN + len);
        byteBuffer.put(BinMessage.MAGIC);
        byteBuffer.put(BinMessage.VERSION);
        byteBuffer.put(message.getType());
        byteBuffer.putShort((short) len);
        byte[] mask = new byte[BinMessage.MASKKEY_LEN];
        for (int i = 0; i < BinMessage.MASKKEY_LEN; i++) {
            mask[i] = (byte) EncryptUtil.random(0, 255);
        }
        byteBuffer.put(mask);
        byte[] bs = BinMessage.afterMask(mask, message.getPayload());
        // 校验码根据掩码运算后的数据计算
        byte[] checksum = BinMessage.checksum(bs);
        byteBuffer.put(checksum);
        byteBuffer.put(bs);
        byteBuffer.flip();
        return byteBuffer;
    }

    public static BinMessage read(ByteBuffer buffer) throws IOException, BadMessageException {
        if (buffer.get() != BinMessage.MAGIC || buffer.get() != BinMessage.VERSION) {
            throw new BadMessageException();
        }
        byte type = buffer.get();

        short slen = buffer.getShort();
        int len = Short.toUnsignedInt(slen);
        byte[] mask = new byte[BinMessage.MASKKEY_LEN];
        buffer.get(mask);

        byte[] checksum = new byte[BinMessage.CHECKSUM_LEN];
        buffer.get(checksum);
        byte[] bs = new byte[len];
        buffer.get(bs);

        if (!checksum(checksum, bs)) {
            throw new BadMessageException();
        }
        bs = BinMessage.afterMask(mask, bs);
        return BinMessage.createMessage(type, bs);

    }

    private static boolean checksum(byte[] checksum, byte[] data) {
        if (checksum.length != BinMessage.CHECKSUM_LEN) {
            return false;
        }
        byte[] cs = BinMessage.checksum(data);
        for (int i = 0; i < BinMessage.CHECKSUM_LEN; i ++) {
            if (cs[i] != checksum[i]) {
                return false;
            }
        }
        return true;
    }
}
